#include <stdio.h>
#include <signal.h>
#include <wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>

void handler(int signo)
{
    // v1
    // printf("收到了%d号信号\n", signo);
    // pid_t rid = waitpid(-1, NULL, 0);
    // if (rid > 0)
    // {
    //     printf("等待子进程成功\n");
    // }
    // v2
    // printf("收到了%d号信号\n", signo);
    // while (true)
    // {
    //     pid_t rid = waitpid(-1, NULL, 0);
    //     if (rid > 0)
    //     {
    //         printf("等待子进程成功\n");
    //     }
    //     else
    //     {
    //         break;
    //     }
    // }
    // v3
    printf("收到了%d号信号\n", signo);
    while (true)
    {
        pid_t rid = waitpid(-1, NULL, WNOHANG);
        if (rid > 0)
        {
            printf("等待子进程成功\n");
        }
        else
        {
            break;
        }
    }
}

int main()
{
    signal(SIGCHLD, handler);
    for (int i = 0; i < 10; i++)
    {
        pid_t id = fork();
        if (id == 0)
        {
            // child process
            int ret = 5;
            while (ret--)
            {
                printf("子进程pid:%d\n", getpid());
                // sleep(1);
            }
            exit(0); // 子进程5秒之后退出
        }
    }
    // father process
    while (true)
    {
        sleep(1);
    }

    return 0;
}

// volatile int g_flag = 0;
// void handler(int signo)
// {
//     (void)signo;
//     printf("将g_flag由%d->%d\n", g_flag, 1);
//     g_flag = 1;
// }
// int main()
// {
//     signal(2, handler);
//     while (g_flag == 0); // 当收到2号信号时,进程退出
//     // 当我们在不同平台下写代码,此时,编译器会对我们写的代码进行自动优化
//     // 自动优化---编译器检测到在main函数中,没有对g_flag全局变量进行更改,
//     // 此时,编译器就会将g_flag从内存中放到寄存器中
//     // 所以,每次进行while判断时,就从寄存器中读取g_flag,而不从内存中读取,提高读取效率
//     // 但一旦产生优化,就可能会产生与结果预期不一致的情况
//     // gcc中自动优化代码选项 -O0 -O1 -O2 -O3,默认为-O0(不做优化),1-3为优化等级
//     // 自动优化之后，就会出现与结果预期不一致的情况
//     // 因为编译器的优化,影响了预期结果
//     // 解决方案:使用volatile关键字修饰此g_flag,屏蔽此优化
//     printf("进程退出\n");
//     return 0;
// }